package com.cbarmstrong.Finance;

import java.awt.Color;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Vector;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYSplineRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.time.TimeSeriesDataItem;

public class RangeIndicator implements Indicator {

	private HashMap<Date, Integer> indicatorValues=new HashMap<Date, Integer>();
	private String representation;
	
	@SuppressWarnings("unchecked")
	public RangeIndicator(String rHigh, String series, String rLow, Ticker ticker, int mode){
		//Data.getLogger().fine("Creating Range indicator, indside: "+inside+" - from:");
		//Data.getLogger().fine(rHigh);
		//Data.getLogger().fine(series);
		//Data.getLogger().fine(rLow);
		boolean inside=mode==0;
		boolean outsideAgainstTrend=mode==1;
		boolean outsideWithTrend=mode==2;
		Data.getLogger().finest("inside: "+inside+", outsideAgainstTrend: "+outsideAgainstTrend+", outsideWithTrend: "+outsideWithTrend);
		Vector<Double> diff1 = Data.differenceSet(Indicators.getIndicator(rHigh, ticker).getValues(), Indicators.getIndicator(series, ticker).getValues(), new Vector<Double>());
		Vector<Double> diff2 = Data.differenceSet(Indicators.getIndicator(series, ticker).getValues(), Indicators.getIndicator(rLow, ticker).getValues(), new Vector<Double>());
		representation="range "+rHigh+" "+series+" "+rLow+" "+mode;
		for(int i=0;i<diff1.size();i++){
			try{
				if(inside){
					if(diff1.get(i)>0 && diff2.get(i)>0){
						indicatorValues.put(ticker.getDates().get(i), null);
					}
					else{
						indicatorValues.put(ticker.getDates().get(i), 0);
					}
				}
				else{
					if(diff1.get(i)<0){
						if(outsideWithTrend){ indicatorValues.put(ticker.getDates().get(i), 1); }
						if(outsideAgainstTrend){ indicatorValues.put(ticker.getDates().get(i), -1); }
					}
					else if(diff2.get(i)<0){
						if(outsideWithTrend){ indicatorValues.put(ticker.getDates().get(i), -1); }
						if(outsideAgainstTrend){ indicatorValues.put(ticker.getDates().get(i), 1); }
					}
					else{
						indicatorValues.put(ticker.getDates().get(i), 0);	
					}
				}
			} catch(NullPointerException e){
				indicatorValues.put(ticker.getDates().get(i), 0);
			}
			Data.getLogger().finest("Position: "+indicatorValues.get(ticker.getDates().get(i))+", date: "+ticker.getDates().get(i));
		}
	}
	
	@Override
	public Integer position(Date date) {
		//Data.getLogger().fine("Value at "+date+": "+indicatorValues.get(date));
		//Data.getLogger().fine("For "+representation);
		return indicatorValues.get(date);
	}

	@SuppressWarnings("rawtypes")
	@Override
	public Vector getValues() {
		return null;
	}

	@Override
	public int days() {
		return indicatorValues.size();
	}
	
	public String save(){
		return representation;
	}

	@SuppressWarnings("unchecked")
	public void toGraph(Ticker ticker, OutputStream out, int x, int y){
		Vector<Double> high=Indicators.getIndicator(representation.split(" ")[1], ticker).getValues();
		Vector<Double> series=Indicators.getIndicator(representation.split(" ")[2], ticker).getValues();
		Vector<Double> low=Indicators.getIndicator(representation.split(" ")[3], ticker).getValues();
		boolean inside=representation.split(" ")[4].compareTo("0")==0;
		TimeSeriesCollection dataset=new TimeSeriesCollection();
		int seriesCounter=1;
		TimeSeries t1=new TimeSeries(seriesCounter++);
		TimeSeries t2=new TimeSeries(seriesCounter++);
		TimeSeries t3=new TimeSeries(seriesCounter++);
		ArrayList<Color> colours = new ArrayList<Color>();
		int state;
		if(position(ticker.getDates().get(0)) != null){
			state=position(ticker.getDates().get(0));
			if(state==1){ colours.add(Color.green); }
			if(state==0){ if(inside) colours.add(Color.YELLOW); else colours.add(Color.black); }
			if(state==-1){ colours.add(Color.red); }
		} else{
			state=2;
			colours.add(Color.green);
		}
		for(int i=0;i<ticker.getDates().size();i++){
			boolean renewSets=false;
			if(position(ticker.getDates().get(i)) != null){
				if(state!=position(ticker.getDates().get(i))){
					state=position(ticker.getDates().get(i));
					if(state==1){ colours.add(Color.green); }
					if(state==0){ if(inside) colours.add(Color.YELLOW); else colours.add(Color.black); }
					if(state==-1){ colours.add(Color.red); }
					renewSets=true;
				} 
			} else{
				if(state!=2){
					state=2;
					colours.add(Color.green);
					renewSets=true;
				}
			}
			if(renewSets){
				t2.add(new TimeSeriesDataItem(new Day(ticker.getDates().get(i)), series.get(i)));
				Data.getLogger().finest("Resetting Timeseries on "+ticker.getDates().get(i)+" state: "+state+", position: "+position(ticker.getDates().get(i)));
				try {
					dataset.addSeries((TimeSeries) t2.clone());
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}
				t2=new TimeSeries(seriesCounter++);
			}
			t1.add(new TimeSeriesDataItem(new Day(ticker.getDates().get(i)), high.get(i)));
			t2.add(new TimeSeriesDataItem(new Day(ticker.getDates().get(i)), series.get(i)));
			t3.add(new TimeSeriesDataItem(new Day(ticker.getDates().get(i)), low.get(i)));
		}
		dataset.addSeries(t2);
		dataset.addSeries(t1);
		dataset.addSeries(t3);
		JFreeChart chart = ChartFactory.createTimeSeriesChart(representation, "Time", "Values", dataset, false, false, false);
		XYPlot plot = (XYPlot) chart.getPlot();
		plot.setRenderer(new XYSplineRenderer(50));
		int j=0;
		((XYSplineRenderer) plot.getRenderer()).setSeriesShapesVisible(plot.getSeriesCount()-2, false);
		plot.getRenderer().setSeriesPaint(plot.getSeriesCount()-2, Color.gray);
		((XYSplineRenderer) plot.getRenderer()).setSeriesShapesVisible(plot.getSeriesCount()-1, false);
		plot.getRenderer().setSeriesPaint(plot.getSeriesCount()-1, Color.darkGray);
		for(int i=0;i<plot.getSeriesCount()-2;i++){
			((XYSplineRenderer) plot.getRenderer()).setSeriesShapesVisible(i, false);
			plot.getRenderer().setSeriesPaint(i, colours.get(j++));
		}
		try {
			ChartUtilities.writeChartAsJPEG(out, chart, x, y);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


	
}
